from flask import Flask, jsonify, request, make_response, g
from flask_cors import CORS
from flask_socketio import SocketIO
import signal
import atexit
import time
from utils.logger import setup_default_logger, info, error, debug, warning, critical
from utils.system_monitor import start_monitoring, stop_monitoring
from utils.database import init_db_pool, close_db_pool
from utils.redis_client import init_redis_pool, close_redis_pool
from utils.exceptions import APIException, ServerError, ResourceNotFoundError
from utils.scheduler import get_scheduler, shutdown_scheduler
from utils.system_pusher import get_pusher, start_pushing
from utils.system_summary import get_summarizer, start_summary
# 设置默认日志器
logger = setup_default_logger(
    level="INFO",  # DEBUG级别
    log_to_console=True,
    log_to_file=True,
    daily_rotation=True,  # 按天切割日志
    format_str="%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s"
)

app = Flask(__name__)
CORS(app)

from utils.extensions import socketio

# 将socketio实例与app关联
socketio.init_app(app)

# 注册蓝图
from api.realtime_data import realtime_data_bp
from api.error_demo import error_demo_bp
from api.summary_data import summary_data_bp
app.register_blueprint(realtime_data_bp)
app.register_blueprint(error_demo_bp)
app.register_blueprint(summary_data_bp)

@app.errorhandler(404)
def page_not_found(e):
    warning(f"404错误: {request.path}")
    return jsonify({"status": "error", "message": "页面不存在"}), 404

@app.errorhandler(500)
def internal_server_error(e):
    warning(f"500错误: {str(e)}")
    return jsonify({"status": "error", "message": "服务器内部错误"}), 500


@app.before_request
def before_request():
    """在请求处理前记录开始时间"""
    g.start_time = time.time()

@app.after_request
def after_request(response):
    """在请求处理后记录结束时间并计算耗时"""
    # 确保所有JSON响应都设置正确的Content-Type头
    if response.mimetype == 'application/json':
        response.headers['Content-Type'] = 'application/json; charset=utf-8'
    
    # 计算请求处理时间
    if hasattr(g, 'start_time'):
        elapsed_time = time.time() - g.start_time
        # 获取请求路径和方法
        path = request.path
        method = request.method
        # 记录接口调用耗时
        info(f"接口耗时统计 | 路径: {path} | 方法: {method} | 耗时: {elapsed_time:.4f}秒")
    
    return response



if __name__ == '__main__':
    info("服务器启动")
    # 初始化全局调度器
    scheduler = get_scheduler()
    info("全局调度器已初始化")
    
    # 启动系统监控，每60秒记录一次系统状态
    start_monitoring(interval=60, scheduler=scheduler)

    info("系统监控已启动")
    # 初始化系统数据推送器
    pusher = get_pusher(2)
    info("全局系统数据推送器初始化")
    start_pushing(2, scheduler)
    info("全局系统数据推送器已启动")
    start_summary(scheduler)
    # 初始化数据库连接池
    init_db_pool(
        host='139.196.93.182',
        port=3306,
        user='root',
        password='jiankekejian',
        database='welfare',
        max_connections=10,
        min_connections=1
    )
    info("数据库连接池已初始化")
    
    # 初始化Redis连接池
    init_redis_pool(
        host='139.196.93.182',
        port=6379,
        password='jiankekejian',
        db=0,
        max_connections=10,
        decode_responses=True
    )
    info("Redis连接池已初始化")
    
    # 定义清理函数
    def cleanup_resources():
        """清理所有资源，包括调度器、系统监控、数据库连接池和Redis连接池"""
        info("开始清理资源...")
        # 停止系统监控
        stop_monitoring(scheduler)
        info("系统监控已停止")
        
        # 关闭调度器
        shutdown_scheduler()
        info("调度器已关闭")
        
        # 关闭数据库连接池
        close_db_pool()
        info("数据库连接池已关闭")
        
        # 关闭Redis连接池
        close_redis_pool()
        info("Redis连接池已关闭")
        
        info("所有资源已清理完毕")
    
    # 注册信号处理函数
    def signal_handler(sig, frame):
        """处理终止信号"""
        info(f"接收到信号 {sig}，准备关闭应用...")
        cleanup_resources()
        info("应用已安全关闭")
        import sys
        sys.exit(0)
    
    # 注册SIGINT和SIGTERM信号处理函数
    signal.signal(signal.SIGINT, signal_handler)  # Ctrl+C
    signal.signal(signal.SIGTERM, signal_handler)  # kill
    
    # 注册应用正常退出时的清理函数
    atexit.register(cleanup_resources)
    
    info("信号处理和退出清理函数已注册")
    
    socketio.run(app=app, debug=False, host='0.0.0.0', port=9000, use_reloader=False, allow_unsafe_werkzeug=True)